﻿#pragma once

#include "SP.h"
#include "SPInput.h"

namespace SP
{
	class SPParticleSystem;
	class SPActor;
	class SPWorld;
	class SPGame;
	class SPMap;
	class SPPawn;
	class SPController;
	class SPPlayerController;
	class SPPlayerCamera;
	typedef std::list<SPActor*> SPActorList;
	typedef std::list<SPController*> SPControllerList;

	//-------------------------------------------------------------
	class SPParticleSystem
	{
	public:
		SPParticleSystem( SPParticleSystem* archetype );
		SPParticleSystem( const WCHAR* path );
		~SPParticleSystem();
		
		enum
		{
			EMITTER_NONE,
			EMITTER_MESH,
			EMITTER_PARTICLE,
			EMITTER_ANIMTRAIL,
			EMITTER_BEAM
		};

		SPEmitterList m_EmitterList;
	};
	

	//-------------------------------------------------------------
	class SPObject
	{
	public:
		FLOAT AngleBetweenVector( XMVECTOR vFrom, XMVECTOR vTo );
		XMVECTOR Rot2Dir( XMVECTOR vRot );
		XMVECTOR Dir2Rot( XMVECTOR vDir );

		void GetAxes( XMVECTOR vIn, XMVECTOR& vX, XMVECTOR& vY, XMVECTOR& vZ );
		XMVECTOR XOnly( XMVECTOR vIn );
		XMVECTOR YOnly( XMVECTOR vIn );
		XMVECTOR ZOnly( XMVECTOR vIn );
		XMVECTOR WOnly( XMVECTOR vIn );
	};

	class SPActor : public SPObject
	{
	protected:
		SPActor();
		virtual ~SPActor();

	public:
		void AddChild( SPActor* child );
		void RemoveChild( SPActor* child );

		void Advance( float fElapsedTime );
		void RenderDepthEnableEmitter();
		void RenderDepthDisableEmitter();

		XMFLOAT3				m_vLocation;
		XMFLOAT4				m_vRotation;
		XMFLOAT3				m_vScale;
		XMFLOAT3				m_vVelocity;
		XMFLOAT3				m_vAcceleration;
		XMFLOAT3				m_vDirection;
		
		XMFLOAT4X4			m_mTransform;

		SPActor*					m_pOwner;
		bool							m_bFollowOwner;

		static SPWorld*			m_pWorld;


		//virtual void OnCollision( SPActor* other );
		virtual void PostBeginPlay();
		virtual void OnAdvance( float fElapsedTime );
		virtual void UpdateLocation( float fElapsedTime );
		virtual XMMATRIX ComputeTransformMatrix();	

		void SetRotation( XMVECTOR qRot );
		void Rotate( XMVECTOR qRotDelta );
		void SetRotation( FLOAT Pitch, FLOAT Yaw, FLOAT Roll );		
		void Rotate( FLOAT fPitchDelta, FLOAT fYawDelta, FLOAT fRollDelta );
		void SetDirection( const XMFLOAT3& vDir );

		void TransformEmitter( CXMMATRIX m );
	protected:		
		void SpawnEmittters( SPParticleSystem* archetype );			
		void SpawnEmitter( SPEmitter* archetype );

		SPActorList				m_ActorList;
		SPEmitterList				m_EmitterList;

	private:
		bool m_bBegined;
	}; 


	//-------------------------------------------------------------
	class SPWorld : public SPActor
	{
	public:
		SPWorld();
		virtual ~SPWorld();

		void OnFrameRender();
		void OnFrameMove( float fElapsedTime );

		void LoadGame( SPGame* pGame );

		SPInput*	m_pInput;	
		SPGame* m_gGame;
	};


	//-------------------------------------------------------------
	class SPGame : public SPActor
	{
	public:
		SPGame();
		virtual ~SPGame();

		virtual void PostBeginPlay();
		virtual void StartMatch();
		virtual void EndMatch();
		virtual SPPlayerController* SpawnPlayer();

		virtual void OnAdvance( float fElapsedTime );

		void SetPlayer( SPPlayerController* pPlayer );
		void AddBot( SPController* pBot );
		void RemoveBot( SPController* pBot );

		SPPlayerController* m_pPlayerController;
		SPControllerList m_ControllerList;
	
		SPMap* m_pMap;

		bool m_bStarted;
		bool m_bGameOver;
	};


	//-------------------------------------------------------------
	class SPMap
	{
	public:
		XMFLOAT3 m_vPalyerStartPoint;
		SPGame* m_pOwnerGame;
	};


	//-------------------------------------------------------------
	class SPPawn : public SPActor
	{
	public:
		SPPawn( SPController* pController );
		~SPPawn();

		SPController* m_pController;
	};


	//-------------------------------------------------------------
	class SPController : public SPActor
	{
	public:
		SPController();
		~SPController();
	
		virtual void PostBeginPlay();
		virtual SPPawn* SpawnPawn();
		SPPawn* m_pPawn;
	};


	//-------------------------------------------------------------
	class SPPlayerController : public SPController
	{
	public:
		SPPlayerController();
		~SPPlayerController();

		virtual void PostBeginPlay();
		virtual SPPawn* SpawnPawn();
		virtual SPPlayerCamera* SpawnPlayerCamera();
		virtual void OnAdvance( float fElapsedTime );

		SPPlayerCamera* m_pPlayerCamera;
	};


	//-------------------------------------------------------------
	class SPPlayerCamera : public SPActor
	{
	public:
		SPPlayerCamera( SPPlayerController* pOwnerController );
		~SPPlayerCamera();

		virtual void OnAdvance( float fElapsedTime );

		SPPlayerController* m_pOwnerController;
		SPCamera* m_pSPCamera;

		XMFLOAT3 m_vEye;
		XMFLOAT3 m_vLookAt;
		XMFLOAT3 m_vUp;
	};

}


